package com.violet.string;

/**
 * @author Violet
 * @Date 2022/4/28
 * @Description 1309 解码字母到整数映射
 * 给你一个字符串s，它由数字（'0' - '9'）和'#'组成。我们希望按下述规则将s映射为一些小写英文字符：
 * 字符（'a' - 'i'）分别用（'1' -'9'）表示。
 * 字符（'j' - 'z'）分别用（'10#'-'26#'）表示。
 * 返回映射之后形成的新字符串。题目数据保证映射始终唯一。
 * <p>
 * 输入：s = "10#11#12"
 * 输出："jkab"
 * 解释："j" -> "10#" , "k" -> "11#" , "a" -> "1" , "b" -> "2".
 */
public class AlphabetToIntegerMapping {

    public static void main(String[] args) {
        String s1 = "10#11#12";
        String s2 = "1326#";

        System.out.println(alphabetToInteger01(s1));
        System.out.println(alphabetToInteger01(s2));

        System.out.println(alphabetToInteger02(s1));
        System.out.println(alphabetToInteger02(s2));
    }

    public static String alphabetToInteger01(String s) {
        // 定义数字和字母映射的关系
        String alphabet = "abcdefghijklmnopqrstuvwxyz";
        // 用来接收返回的结果
        StringBuilder resultSb = new StringBuilder();
        // 用来从左向右依次扫描需要转换的 str，以一个 # 为扫描结束条件
        StringBuilder scanSb = new StringBuilder();
        // 扫描到的str类型
        String scanStr;
        // 输入内容映射在字母str中的索引
        int index;

        char[] chars = s.toCharArray();
        // 依次扫描
        for (int i = 0; i < chars.length; i++) {

            /*
             * 判断是否遇到 #
             *  是：以此为节点，处理扫描到的字符
             *  否：将扫描的字符添加到scanSb，继续扫描
             * */
            if ('#' == chars[i]) {
                scanStr = scanSb.toString();
                /*
                 * 判断扫描到的字符串长度是否为2，即该字符串是否满足只包含 j - z
                 *  是：直接转换
                 *  否：包含两部分，1）最后两位的 j - z 字符；2）前面的 a - i 字符
                 * */
                if (scanStr.length() == 2) {
                    index = Integer.parseInt(scanStr) - 1;
                    resultSb.append(alphabet.charAt(index));

                } else {
                    // 转换前面的字符
                    String frontStr = scanStr.substring(0, scanStr.length() - 2);
                    convertNumAToI(frontStr, alphabet, resultSb);

                    // 转换结尾两位的字符
                    String backStr = scanStr.substring(scanStr.length() - 2);
                    index = Integer.parseInt(backStr) - 1;
                    resultSb.append(alphabet.charAt(index));
                }

                // 每个节点处理完之后，必须清空scanSb中的值
                scanSb.delete(0, scanSb.length());
            } else {
                scanSb.append(chars[i]);

                /*
                 * 判断需要转换的字符串是否到结尾处
                 *  是：表示字符串不是以#结尾，且又到结尾，此时需要对最后一次扫描到的节点做处理
                 * */
                if (i == chars.length - 1) {
                    scanStr = scanSb.toString();
                    convertNumAToI(scanStr, alphabet, resultSb);
                }
            }
        }

        return resultSb.toString();
    }

    /**
     * 转换a-i的字符
     * @param sourceStr 需要转换的str
     * @param alphabet 所有字母str
     * @param resultSb
     */
    private static void convertNumAToI(String sourceStr, String alphabet, StringBuilder resultSb) {
        for (int indexForFrontStr = 0; indexForFrontStr < sourceStr.length(); indexForFrontStr++) {
            String frontChar = String.valueOf(sourceStr.charAt(indexForFrontStr));
            int index = Integer.parseInt(frontChar) - 1;
            resultSb.append(alphabet.charAt(index));
        }
    }

    /**
     * 其他人的解题思路
     * @param s
     * @return
     */
    public static String alphabetToInteger02(String s) {
        StringBuilder ans = new StringBuilder();
        int len = s.length();
        for (int i = 0; i < len; ++i) {
            if (i + 2 < len && s.charAt(i + 2) == '#') {
                // 这里 s.charAt(i + 1) + 'a' - '1'是s.charAt(i + 1) - '0' + 'a' - 1 的简写
                ans.append((char)(10 * (s.charAt(i) - '0') + s.charAt(i + 1) + 'a' - '1'));
                i += 2;
            } else {
                ans.append((char)('a' + s.charAt(i) - '1'));
            }
        }
        return ans.toString();
    }
}
